8. 도커 개요6
2.5. 도커 아키텍처와 OCI 런타임
핵심 개념
Docker는 클라이언트-서버 아키텍처로 구성됨. 사용자가 입력하는 docker 명령어는 클라이언트에 해당하며, 실제 작업은 서버인 Docker Daemon이 수행함.
Docker 아키텍처:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────┐
│ Docker Client │
│ (docker CLI 명령어) │
└─────────────────┬───────────────────────────┘
│ Docker API (HTTP)
▼
┌─────────────────────────────────────────────┐
│ Docker Daemon │
│ ┌───────────────────────────────────────┐ │
│ │ • 이미지 관리 (pull/push) │ │
│ │ • 컨테이너 생명주기 관리 │ │
│ │ • 네트워크 관리 │ │
│ │ • 볼륨 관리 │ │
│ │ • 스토리지 드라이버 (overlay2 등) │ │
│ └───────────────┬───────────────────────┘ │
└──────────────────┼───────────────────────────┘
│
▼
┌─────────────────┐
│ OCI Runtime │
│ (runc 등) │
└─────────────────┘
│
▼
┌─────────────────┐
│ Container │
└─────────────────┘
용어 정리
- 클라이언트-서버 아키텍처: 사용자가 명령을 입력하는 클라이언트와 실제 작업을 수행하는 서버로 분리된 구조. Docker에서는
dockerCLI가 클라이언트, Docker Daemon이 서버 역할을 함 - Docker Client: 사용자가
docker명령어를 입력하는 CLI 도구. Docker API를 통해 Docker Daemon과 통신함 - Docker Daemon: Docker의 핵심 서버 프로세스. 이미지, 컨테이너, 네트워크, 볼륨 등을 관리하고 OCI Runtime을 조율함
- Docker API: Docker Client와 Docker Daemon 간 통신에 사용되는 HTTP 기반 REST API
- OCI Runtime: 실제로 컨테이너를 생성하고 격리 환경을 구성하는 저수준 런타임. runc가 대표적인 구현체
2.5.1. Docker Daemon의 역할
Docker Daemon이 담당하는 작업:
-
이미지 관리
- 레지스트리에서 이미지 Pull/Push
- 로컬 이미지 저장 및 관리
- 이미지 빌드 (BuildKit 사용)
-
컨테이너 생명주기 관리
- 컨테이너 생성, 시작, 중지, 삭제
- 컨테이너 상태 모니터링
-
네트워크 관리
- 가상 네트워크 생성 및 관리
- 컨테이너 간 통신 설정
- 포트 포워딩 관리
-
스토리지 관리
- 볼륨 생성 및 관리
- 스토리지 드라이버 (overlay2, overlayfs 등) 조작
- 레이어 파일시스템 관리
Docker Daemon이 직접 하지 않는 작업:
Docker Daemon은 실제로 컨테이너를 생성하고 실행하는 작업은 직접 수행하지 않음. 이 작업은 OCI Runtime에 위임됨.
용어 정리
- BuildKit: Docker의 차세대 이미지 빌드 엔진. 병렬 빌드, 향상된 캐싱, 빌드 시크릿 지원 등의 기능을 제공함
- 스토리지 드라이버: 컨테이너의 레이어 파일시스템을 관리하는 컴포넌트. overlay2가 현재 기본 드라이버로 사용됨
- 컨테이너 생명주기: 컨테이너가 생성(create)되고, 시작(start)되고, 실행(running) 중이다가, 중지(stop)되고, 삭제(remove)되는 일련의 상태 변화
2.5.2. OCI Runtime (저수준 컨테이너 런타임)
OCI Runtime의 정의:
- OCI (Open Container Initiative): 컨테이너 표준화를 위한 오픈 소스 프로젝트
- OCI Runtime Specification: 컨테이너 런타임이 준수해야 할 표준 규격
- 역할: 호스트와 격리된 실행 환경(컨테이너)을 생성하고 직접 조작
주요 OCI Runtime 구현체:
| 구현체 | 개발 주체 | 격리 기술 | 특징 |
|---|---|---|---|
| runc | OCI | Linux 네임스페이스, cgroups | OCI 참조 구현, 가장 널리 사용됨 |
| gVisor | 사용자 공간 커널 | 보안 강화, 성능 트레이드오프 존재 | |
| Kata Containers | OpenStack Foundation | 경량 가상 머신 | VM 수준 격리, 보안성 높음 |
OCI Runtime의 동작 방식:
컨테이너 실행 흐름:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
사용자 입력:
$ docker run nginx
↓
Docker Daemon:
1. nginx 이미지 확인/다운로드
2. 컨테이너 설정 준비
3. OCI Runtime에 실행 요청
↓
OCI Runtime (runc):
1. Linux 네임스페이스 생성
- PID, NET, MNT, UTS, IPC 네임스페이스
2. cgroups 설정
- CPU, 메모리 제한
3. 루트 파일시스템 마운트
- overlayfs로 레이어 병합
4. 프로세스 실행
↓
격리된 컨테이너 환경 생성 완료
용어 정리
- OCI (Open Container Initiative): 컨테이너 포맷과 런타임에 대한 개방형 업계 표준을 만들기 위한 프로젝트. Docker, Google, CoreOS 등이 참여함
- OCI Runtime Specification: OCI에서 정의한 컨테이너 런타임 표준 규격. 이를 준수하면 어떤 런타임이든 상호 호환 가능
- runc: OCI Runtime Specification의 참조 구현체. Docker의 기본 런타임으로 가장 널리 사용됨
- gVisor: Google이 개발한 보안 강화 런타임. 사용자 공간에서 별도의 커널을 에뮬레이션하여 호스트 커널과 격리함
- Kata Containers: 경량 가상 머신을 사용하여 VM 수준의 격리를 제공하는 런타임. 보안이 중요한 환경에서 사용
- Linux 네임스페이스: 프로세스 격리를 위한 Linux 커널 기능. PID(프로세스), NET(네트워크), MNT(마운트), UTS(호스트명), IPC(프로세스 간 통신) 등의 자원을 격리함
- cgroups (Control Groups): Linux 커널의 리소스 제한 기능. CPU, 메모리, 디스크 I/O 등의 사용량을 제한하고 모니터링함
2.5.3. Docker 전체 실행 흐름
예제: docker run 명령어 실행 시 전체 흐름
┌──────────────────────────────────────────────┐
│ $ docker run -p 8080:80 nginx │
└────────────────┬─────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 1. Docker Client → Docker API 호출 │
│ - HTTP POST /containers/create │
│ - 이미지: nginx, 포트: 8080:80 │
└────────────────┬─────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 2. Docker Daemon │
│ - nginx 이미지 확인 │
│ - 없으면 Docker Hub에서 pull │
│ - 레이어별로 다운로드 및 저장 │
└────────────────┬─────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 3. Storage Driver (overlay2) │
│ - 이미지 레이어를 overlayfs로 병합 │
│ - 읽기 전용 레이어 + 쓰기 가능 레이어 │
│ - 컨테이너 루트 파일시스템 생성 │
└────────────────┬─────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 4. Docker Daemon → OCI Runtime 호출 │
│ - runc create <container-id> │
│ - 컨테이너 설정(config.json) 전달 │
└────────────────┬─────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 5. OCI Runtime (runc) │
│ - 네임스페이스 생성 (격리) │
│ - cgroups 설정 (리소스 제한) │
│ - 루트 파일시스템 마운트 │
│ - nginx 프로세스 실행 │
└────────────────┬─────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ 6. 컨테이너 실행 완료 │
│ - 포트 8080으로 접속 가능 │
└──────────────────────────────────────────────┘
용어 정리
- overlayfs: 여러 디렉터리를 하나로 병합하여 보여주는 유니온 파일시스템. 이미지의 읽기 전용 레이어들과 컨테이너의 쓰기 가능 레이어를 합쳐 단일 루트 파일시스템으로 제공함
- config.json: OCI Runtime이 컨테이너를 생성할 때 참조하는 설정 파일. 네임스페이스, cgroups, 마운트 포인트, 환경 변수 등의 컨테이너 설정 정보가 담겨 있음
핵심 정리
Docker 아키텍처의 핵심:
- Docker Client: 사용자 명령어 입력
- Docker Daemon: 이미지/네트워크/볼륨 관리, OCI Runtime 조율
- OCI Runtime: 실제 컨테이너 생성 및 격리 환경 구성
중요한 원칙:
Docker Daemon이 OCI Runtime을 조작해서 컨테이너 실행 환경을 작성하고 조작함
이러한 계층 구조 덕분에:
- 다양한 OCI Runtime 선택 가능 (runc, gVisor, Kata Containers)
- 컨테이너 표준(OCI)을 준수하여 상호 운용성 확보
- 보안이나 성능 요구사항에 따라 적절한 런타임 선택 가능
2.6. Docker 학습 정리
학습한 주요 내용
1. Docker의 기본 흐름: Build, Ship, Run
Build Ship Run
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Dockerfile → 이미지 빌드 → 레지스트리 → 컨테이너 실행
2. Docker 사용 방법
- 컨테이너와 호스트 간 파일 공유 (
-v,--mount) - 볼륨을 통한 데이터 영속성 관리
- 포트 포워딩으로 호스트 네트워크 연결 (
-p) - Docker Compose를 활용한 다중 컨테이너 관리
- Dockerfile을 작성하여 커스텀 이미지 빌드
3. 컨테이너 레이어 구조
- 이미지를 실제로 분석하여 레이어 구조 확인
- 레이어가 빌드와 컨테이너 실행에 미치는 영향 이해
- overlayfs를 사용한 컨테이너 루트 파일시스템 작성 원리
4. Docker 아키텍처
- Client-Server 구조
- Docker Daemon의 역할과 책임
- OCI Runtime을 통한 저수준 컨테이너 관리
참고 자료
공식 문서:
- Docker Architecture: https://docs.docker.com/get-started/overview/#docker-architecture
- containerd: https://containerd.io/
- Docker Engine: https://docs.docker.com/engine/
관련 주제:
- OCI Runtime Spec: https://github.com/opencontainers/runtime-spec
- Docker vs Podman: https://docs.podman.io/en/latest/